package com.rory.gooday.common.cron4j;

import com.jfinal.json.Json;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.cron4j.ITask;
import com.jfinal.plugin.redis.Redis;
import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

public class LoadMemorialTask implements ITask {

    @Override
    public void stop() {
    }

    @Override
    public void run() {
        try {
            Redis.call(jedis -> {
                Set<String> keys = jedis.keys("jnr:*");
                if (!keys.isEmpty()) {
                    return jedis.del(keys.toArray(new String[0]));
                }
                return 0L;
            });
            // 注意：建议在memorial表的is_msg和open_count字段上建立复合索引
            // 防止数据量过大导致内存问题，实际使用中应考虑分页处理
            List<Record> memorials = Db.find("select * from memorial where is_msg = '1' and (open_count > 0 or open_count = -1) AND (send_interval_day is not null and send_interval_day != '') and (send_interval_time is not null and send_interval_time != '') LIMIT 10000");
            System.out.println("重载纪念日："+memorials.size());

            memorials.forEach(memorial -> {
                List<Map<String,String>> list = new ArrayList<>(memorials.size());
                Map<String,String> map = new HashMap<>(8);
                map.put("month",memorial.getStr("memorial_day_for_mm"));
                map.put("day",memorial.getStr("memorial_day_for_dd"));
                map.put("send_days",memorial.getStr("send_interval_day"));
                map.put("send_times",memorial.getStr("send_interval_time"));
                map.put("lunar",memorial.getStr("is_lunar"));
                map.put("id",memorial.getStr("id"));
                list.add(map);
                Map<LocalDateTime,List<Integer>> a = getLunarDate(list);

                for (Map.Entry<LocalDateTime, List<Integer>> entry : a.entrySet()) {
                    LocalDateTime dateTime = entry.getKey();
                    long timestamp = dateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
                    List<Integer> ids = entry.getValue();
//                System.out.println("jnr:"+dateTime.getYear()+dateTime.getMonthValue()+":"+dateTime.toString()+"/"+Json.getJson().toJson(ids));
                    Redis.call(jedis -> {
                        return jedis.set("jnr:"+dateTime.getYear()+dateTime.getMonthValue()+":"+timestamp, Json.getJson().toJson(ids));
                    });
                }
            });
        } catch (Exception e) {
            // 添加异常处理，避免线程静默失败
            e.printStackTrace(); // 实际项目中应使用proper logging
        }
    }

    private Map<LocalDateTime,List<Integer>> getLunarDate(List<Map<String, String>> list) {
        Map<LocalDateTime,List<Integer>> result = new HashMap<>();
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);

        for (Map<String, String> map : list) {
            if (map == null) continue;
            Set<LocalDateTime> dateTimes = new HashSet<>();

            String monthStr = map.get("month");
            String dayStr = map.get("day");
            String sendDaysStr = map.get("send_days");
            String sendTimesStr = map.get("send_times");
            String lunarStr = map.get("lunar");
            String idStr = map.get("id");

            if (idStr == null || monthStr == null || dayStr == null || sendDaysStr == null || sendTimesStr == null) {
                continue; // 忽略字段缺失的条目
            }

            int id, month, day;
            try {
                id = Integer.parseInt(idStr);
                month = Integer.parseInt(monthStr);
                day = Integer.parseInt(dayStr);
            } catch (NumberFormatException e) {
                continue; // 忽略格式错误的条目
            }

            List<String> sdays;
            List<String> stimes;
            try {
                sdays = Arrays.asList(sendDaysStr.split(","));
                stimes = Arrays.asList(sendTimesStr.split(","));
            } catch (Exception e) {
                continue; // split 异常忽略
            }

            int lunar = 0;
            if (lunarStr != null) {
                try {
                    lunar = Integer.parseInt(lunarStr);
                } catch (NumberFormatException ignored) {
                    // 忽略非法 lunar 值，默认为 0
                }
            }

            List<Solar> solars = new ArrayList<>();

            for (String t : stimes) {
                if (t == null || t.length() < 4) continue;
                try {
                    int hour = Integer.parseInt(t.substring(0, 2));
                    int minute = Integer.parseInt(t.substring(t.length() - 2));
                    if (lunar == 1) {
                        solars.add(new Lunar(currentYear, month, day, hour, minute, 0).getSolar());
                        solars.add(new Lunar(currentYear-1, month, day, hour, minute, 0).getSolar());
                        solars.add(new Lunar(currentYear+1, month, day, hour, minute, 0).getSolar());
                    } else {
                        solars.add(Solar.fromYmdHms(currentYear, month, day, hour, minute, 0));
                    }
                } catch (Exception ignored) {
                    // 忽略时间格式错误项
                }
            }

            for (Solar solar : solars) {
                for (String sday : sdays) {
                    if (sday == null) continue;
                    try {
                        int daysOffset = Integer.parseInt(sday);
                        Solar nextSolar = solar.next(daysOffset);
                        LocalDateTime lday = LocalDateTime.of(
                                nextSolar.getYear(),
                                nextSolar.getMonth(),
                                nextSolar.getDay(),
                                nextSolar.getHour(),
                                nextSolar.getMinute(),
                                nextSolar.getSecond()
                        );
                        dateTimes.add(lday);
                    } catch (Exception ignored) {
                        // 忽略非法偏移量
                    }
                }
            }
            dateTimes.forEach(lday -> {
                result.computeIfAbsent(lday, k -> new ArrayList<>()).add(id);
            });
        }
        return result;
    }
}
